import { AppTask } from "../../app.task.class";
import { Observable, Subject } from "rxjs";
import { SrHttpUploadFileTask } from "./sr.http.upload.file.task";
import { AppCache } from "../../../utils/cache.util";
import { curry } from "ramda";
import { logger } from "../../../configs/log.config";
import { V3proAlertMessageFile, V3proSubjectMessage } from "../../v3pro-task/model/v3pro.model";

const fileCache = new AppCache("4d");

/**
 * 上传文件服务
 */
export class SrHttpUploadServerTask extends AppTask {
  /**
   * 构造函数
   * @param __groupObservable 分组订阅
   * @param __subject 聚合订阅
   */
  constructor(
    private __groupObservable: Observable<V3proSubjectMessage>,
    private __subject: Subject<V3proSubjectMessage>,
  ) {
    super();
    const description = __groupObservable.subscribe(this.__onMessage.bind(this));
    this.onStop = description.unsubscribe.bind(description);
  }

  private __lastUploadTask?: SrHttpUploadFileTask;
  private __appCache = fileCache;
  private __lastMessage?: V3proSubjectMessage;
  private __isUploading = false;

  private async __onMessage(message?: V3proSubjectMessage) {
    if (!message) return;
    if (this.__isUploading) return (this.__lastMessage = message);
    this.__isUploading = true;
    this.__lastUploadTask = new SrHttpUploadFileTask(
      this.__appCache,
      message,
      curry(this.__uploadSuccessCallback.bind(this))(message),
      curry(this.__uploadFailCallback.bind(this)),
    );
    this.__lastUploadTask.start().then();
  }

  private async __uploadSuccessCallback(
    message: V3proSubjectMessage,
    file: V3proAlertMessageFile[],
  ) {
    message.files = file;
    this.__subject.next(message);
    this.__isUploading = false;
    this.__onMessage(this.__lastMessage).then();
    this.__lastMessage = undefined;
  }

  private async __uploadFailCallback(error: Error) {
    logger.error(error);
    this.__isUploading = false;
    this.__onMessage(this.__lastMessage).then();
    this.__lastMessage = undefined;
  }

  __pause(): Promise<boolean> {
    return Promise.resolve(false);
  }

  __restore(): Promise<boolean> {
    return Promise.resolve(false);
  }

  async __run(): Promise<void> {
    await this.__await();
  }

  async __stop(): Promise<boolean> {
    if (this.__lastUploadTask) await this.__lastUploadTask.stop();
    return true;
  }
}
